#include <irq.h>
#include <stdio.h>
#include <timer.h>
#include <camera.h>

#define DEBUG

#define	ClearPending(bit) {	SRCPND = bit; INTPND = bit; INTPND; }

void camera_init(void) {
#ifdef DEBUG
	u32 v_GPJCON = 0x00;
	printf("CAMERA_INITING.....\n");
#endif
	//GPJCON	  = 0x2aaaaaa;
	GPJCON	  = 0x2AAAAAA;
	GPJDAT	  = 0;
	GPJUP	  = 0x1FFF;
	CISRCFMT |=(1<<31);			//set 601 format
	CIGCTRL  |= (1<<31);		// Camera I/F soft reset
	mdelay(100);
	CIGCTRL  &= ~(1<<31);

	CLKCON	 |= (1<<19);		// Enable Camera Clock
#ifdef DEBUG
	v_GPJCON = GPJCON;
	printf("GPJCON => %08x\n",v_GPJCON);
#endif
}

void camera(void) {
#ifdef DEBUG
	printf("in camera()\n");
#endif
	int MainBurstSizeY, MainBurstSizeC, RemainedBurstSizeY, RemainedBurstSizeC;

	CIGCTRL |= (1<<26); // inverse PCLK ??

	CISRCFMT =(0<<31)|(1<<30)|(0<<29)|(CoDstWidth<<16)|(0<<14)|(CoDstHeight);	//ITU-R 656 Cb,Cr Value offset +128 for YUV

	CICOYSA1  = CAMERA_DMA_ADDRESS;					//1	//Y 1st frmae start address for codec DMA
	CICOYSA2  = CICOYSA1+CoDstWidth*CoDstHeight*2;		//2//Y 2nd frmae start address for codec DMA
	CICOYSA3  = CICOYSA2+CoDstWidth*CoDstHeight*2;		//3//Y 3nd frmae start address for codec DMA
	CICOYSA4  = CICOYSA3+CoDstWidth*CoDstHeight*2;		//4//Y 4th frmae start address for codec DMA

	CICOCBSA1 = CICOYSA1+CoDstWidth*CoDstHeight;		//1
	CICOCBSA2 = CICOYSA2+CoDstWidth*CoDstHeight;
	CICOCBSA3 = CICOYSA3+CoDstWidth*CoDstHeight;
	CICOCBSA4 = CICOYSA4+CoDstWidth*CoDstHeight;

	CICOCRSA1 = CICOCBSA1+CoDstWidth*CoDstHeight/2;
	CICOCRSA2 = CICOCBSA2+CoDstWidth*CoDstHeight/2;
	CICOCRSA3 = CICOCBSA3+CoDstWidth*CoDstHeight/2;
	CICOCRSA4 = CICOCBSA4+CoDstWidth*CoDstHeight/2;

	CICOTRGFMT = (1<<31)|(1<<30)|(CoDstWidth<<16)|(0<<14)|(CoDstHeight);		//target image fromat of codec DMA

	CalculateBurstSize(CoDstWidth, &MainBurstSizeY, &RemainedBurstSizeY);
	CalculateBurstSize(CoDstWidth/2, &MainBurstSizeC, &RemainedBurstSizeC);

	CICOCTRL = (MainBurstSizeY<<19)|(RemainedBurstSizeY<<14)|(MainBurstSizeC<<9)|(RemainedBurstSizeC<<4);

	SUBSRCPND |= (1<<11);
	ClearPending(1<<6);

	irq_request( 6, camera_irq );

	CamCodecIntUnmask();

	CamCaptureStart();
}

void camera_irq(void) {

	printf("Camera Interrupt On!\n");

	if( SUBSRCPND & (1<<11) ) {			//Codec Path MASK
		CamCodecIntMask();
		SUBSRCPND |= (1<<11);
		ClearPending(1<<6);

		CamCodecIntUnmask();
	}
}

void CalculateBurstSize(u32 hSize, u32 *mainBurstSize, u32 *remainedBurstSize) {
	u32 tmp;	
	tmp=(hSize/4)%16;

	switch(tmp) {
		case 0:
			*mainBurstSize=16;
			*remainedBurstSize=16;

			break;

		case 4:
			*mainBurstSize=16;
			*remainedBurstSize=4;

			break;

		case 8:
			*mainBurstSize=16;
			*remainedBurstSize=8;

			break;

		default: 
			tmp=(hSize/4)%8;

			switch(tmp) {
				case 0:
					*mainBurstSize=8;
					*remainedBurstSize=8;

					break;

				case 4:
					*mainBurstSize=8;
					*remainedBurstSize=4;

				default:
					*mainBurstSize=4;
					tmp=(hSize/4)%4;
					*remainedBurstSize= (tmp) ? tmp: 4;

					break;
			}

			break;
	}		    	    		
}

void CamCodecIntMask(void) {
	INTSUBMSK |= (1<<11);	// INT CAMERA Port B ENABLE 
	INTMSK 	  |= (1<<6);
}

void CamCodecIntUnmask(void) {
	INTSUBMSK &= ~(1<<11);			// INT CAMERA Port B ENABLE 
	INTMSK    &= ~(1<<6);
}

void CamCaptureStart(void) { 
#ifdef DEBUG
	printf("in CamCapturestart \n");
#endif
	CIWDOFST = (1<<30)|(0xf<<12); // clear overflow
	CIWDOFST = 0;

	CICOSCCTRL |= (1<<31);
	
	CIIMGCPT   |= (1<<31); 
}
